package com.mallcloud.mall.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mallcloud.mall.converter.SkuConverter;
import com.mallcloud.mall.converter.SpuConverter;
import com.mallcloud.mall.product.api.dto.*;
import com.mallcloud.mall.product.api.entity.*;
import com.mallcloud.mall.product.api.vo.AppSpuVO;
import com.mallcloud.mall.common.core.constant.CacheConstants;
import com.mallcloud.mall.product.api.vo.AttrExtendVO;
import com.mallcloud.mall.product.api.vo.SpuVO;
import com.mallcloud.mall.product.mapper.AttrMapper;
import com.mallcloud.mall.product.mapper.SpuMapper;
import com.mallcloud.mall.product.service.SkuService;
import com.mallcloud.mall.product.service.SpuAttrValueService;
import com.mallcloud.mall.product.service.SpuDetailService;
import com.mallcloud.mall.product.service.SpuService;
import lombok.AllArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * spu信息
 */
@Service
@AllArgsConstructor
public class SpuServiceImpl extends ServiceImpl<SpuMapper, SpuModel> implements SpuService {
    private final SpuDetailService spuDetailService;
    private final SkuService skuService;
    private final SpuConverter spuConverter;
    private final SpuAttrValueService spuAttrValueService;
    private final AttrMapper attrMapper;

    @Override
    public String getDetail(Long spuId) {
        SpuDetailModel spuDetail = spuDetailService.getOne(Wrappers.<SpuDetailModel>lambdaUpdate().eq(SpuDetailModel::getSpuId, spuId));
        if (spuDetail == null) {
            return "";
        }

        return spuDetail.getDetail();
    }

    @Override
    @Cacheable(cacheNames = CacheConstants.SPU_KEY, key = "#spuId", sync = true)
    public AppSpuVO getBySpuId(Long spuId) {
        return this.baseMapper.getBySpuId(spuId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean publish(SpuPublishDTO dto) {
        SpuModel spu = spuConverter.DTOToModel(dto);
        spu.setPriceFee(dto.getSkuPublishList().get(0).getPriceFee().multiply(BigDecimal.valueOf(100)));
        spu.setMarketPriceFee(dto.getSkuPublishList().get(0).getMarketPriceFee().multiply(BigDecimal.valueOf(100)));
        spu.setHasSkuImg(Boolean.TRUE);
        spu.setStatus(Boolean.TRUE);
        this.save(spu);
        Long spuId = spu.getSpuId();

        //规格
        List<AttrExtendDTO> attrExtendList = dto.getSpuAttrList().stream()
                .map(x -> new AttrExtendDTO(x.getParentId(), x.getId()))
                .collect(Collectors.toList());
        List<AttrExtendVO> attrExtends = attrMapper.extendAttr(attrExtendList);
        List<SpuAttrValueModel> spuAttrValueList = attrExtends.stream()
                .map(x -> {
                    SpuAttrValueModel m = spuConverter.VOToModel(x);
                    m.setSpuId(spuId);
                    return m;
                })
                .collect(Collectors.toList());
        spuAttrValueList.forEach(spuAttrValueService::save);

        // 商品拓展信息
        SpuExtensionModel spuExtension = new SpuExtensionModel();
        spuExtension.setSpuId(spuId);
        spuExtension.setStock(dto.getStock());
        spuExtension.setActualStock(dto.getStock());
        spuExtension.setLockStock(0);
        spuExtension.setSaleNum(0);
        // 商品详情
        SpuDetailModel spuDetail = new SpuDetailModel();
        spuDetail.setSpuId(spuId);
        spuDetail.setDetail(dto.getDetail());
        spuDetailService.save(spuDetail);
        // sku
        skuService.saveSkuPublish(spuId, spu.getName(), dto.getSkuPublishList());
        return Boolean.TRUE;
    }

    @Override
    public IPage<SpuVO> pageSpu(Page page, SpuModel dto) {
        IPage<SpuVO> pageRes = this.page(page, Wrappers.<SpuModel>lambdaQuery()
                .eq(Objects.nonNull(dto.getBrandId()), SpuModel::getBrandId, dto.getBrandId())
                .eq(Objects.nonNull(dto.getCategoryId()), SpuModel::getCategoryId, dto.getCategoryId())
                .eq(Objects.nonNull(dto.getShopId()), SpuModel::getShopId, dto.getShopId())
                .eq(Objects.nonNull(dto.getStatus()), SpuModel::getStatus, dto.getStatus())
                .like(StrUtil.isNotBlank(dto.getName()), SpuModel::getName, dto.getName())
                .orderByDesc(SpuModel::getSpuId)
        );
        pageRes.getRecords().forEach(x ->{
            x.setPriceFee(x.getPriceFee().divide(BigDecimal.valueOf(100), 2));
            x.setMarketPriceFee(x.getMarketPriceFee().divide(BigDecimal.valueOf(100), 2));
        });
        return pageRes;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean saveSpu(SpuDTO dto) {
        SpuModel spuModel = BeanUtil.copyProperties(dto, SpuModel.class);
        spuModel.setPriceFee(dto.getPriceFee().multiply(BigDecimal.valueOf(100)));
        spuModel.setMarketPriceFee(dto.getMarketPriceFee().multiply(BigDecimal.valueOf(100)));

        this.save(spuModel);
        Long spuId = spuModel.getSpuId();

        SpuDetailModel spuDetailModel = BeanUtil.copyProperties(dto, SpuDetailModel.class);
        spuDetailModel.setSpuId(spuId);
        return spuDetailService.save(spuDetailModel);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateSpu(SpuDTO dto) {
        SpuModel spuModel = BeanUtil.copyProperties(dto, SpuModel.class);
        spuModel.setPriceFee(dto.getPriceFee().multiply(BigDecimal.valueOf(100)));
        spuModel.setMarketPriceFee(dto.getMarketPriceFee().multiply(BigDecimal.valueOf(100)));

        this.updateById(spuModel);

        SpuDetailModel spuDetailModel = BeanUtil.copyProperties(dto, SpuDetailModel.class);
        return spuDetailService.saveOrUpdate(spuDetailModel);
    }
}
